unit Checkers.Borders;

interface

uses
  System.Types,
  Classes,
  GLScene,
  GLObjects,
  GLSGenerics,
  GLRenderContextInfo,
//Project
  Checkers.BorderPlane;

type
  TPlanesList = GList<TBorderPlane>;
//Board's borders class, sizes can be changed in constructor method.
  TCheckersBorder = class(TGLBaseSceneObject)
  private
    FBoardWidth: Single;
    FBoardHeight: Single;
    FSize: Single;
    FLeft: TBorderPlane;
    FTop: TBorderPlane;
    FRight: TBorderPlane;
    FBottom: TBorderPlane;
    FLeftTop: TBorderPlane;
    FLeftBottom: TBorderPlane;
    FRightTop: TBorderPlane;
    FRightBottom: TBorderPlane;
    FLeftDown: TBorderPlane;
    FRightDown: TBorderPlane;
    FTopDown: TBorderPlane;
    FBottomDown: TBorderPlane;
    FHPlanes: TPlanesList;
    FPlanes: TPlanesList;
    procedure AddPlane(var APlane: TBorderPlane; const ATexture:String);
    procedure AddDownPlane(var APlane: TBorderPlane; const ATexture: String);
    function GetBorderSize: Single;
    procedure SetBorderSize(const Value: Single);
    procedure SetHeight(const Value: Single);
    function GetFullWidth: Single;
    function GetFullHeight: Single;
    function GetPlanes: TPlanesList;
  public
    constructor Create(AOwner: TComponent); override;
    procedure DoRender(var ARci: TRenderContextInfo; ARenderSelf: Boolean;
      ARenderChildren: Boolean); override;
    procedure SetBoardSize(const AWidth, AHeight: Single);
    destructor Destroy; override;
    property BorderSize: Single read GetBorderSize write SetBorderSize;
    property Height: Single write SetHeight;
    property FullWidth: Single read GetFullWidth;
    property FullHeight: Single read GetFullHeight;
    property Planes: TPlanesList read GetPlanes;
  end;

implementation

{ TCheckersBorder }

constructor TCheckersBorder.Create(AOwner: TComponent);
begin
  inherited;
  FHPlanes := TPlanesList.Create;
  FPlanes := TPlanesList.Create;
  AddPlane(FLeft, 'left');
  AddPlane(FRight, 'right');
  AddPlane(FTop, 'top');
  AddPlane(FBottom, 'bottom');
  AddPlane(FLeftTop, 'left_top');
  AddPlane(FLeftBottom, 'left_bottom');
  AddPlane(FRightTop, 'right_top');
  AddPlane(FRightBottom, 'right_bottom');
  AddDownPlane(FLeftDown, 'left');
  AddDownPlane(FRightDown, 'right');
  AddDownPlane(FTopDown, 'left');
  AddDownPlane(FBottomDown, 'right');
  FLeftDown.Direction.SetVector(-1, 0, 0);
  FRightDown.Direction.SetVector(1, 0, 0);
  FTopDown.Direction.SetVector(0, 0, -1);
  FBottomDown.Direction.SetVector(0, 0, 1);
  BorderSize := 0.5;
  Height := 0.2;
end;

procedure TCheckersBorder.AddDownPlane(var APlane: TBorderPlane; const ATexture:String);
begin
  APlane := TBorderPlane.CreateAsChild(Self);
  APlane.Material.Texture.Enabled := True;
  APlane.Material.Texture.Image.LoadFromFile('Textures\Borders\' + ATexture + '.png');
  APlane.Height := 0.2;
  APlane.Position.Y := -0.5;
  FPlanes.Add(APlane);
end;

procedure TCheckersBorder.AddPlane(var APlane: TBorderPlane; const ATexture:String);
begin
  APlane := TBorderPlane.CreateAsChild(Self);
  APlane.Direction.SetVector(0, 1, 0);
  APlane.Material.Texture.Enabled := True;  
  APlane.Material.Texture.Image.LoadFromFile('Textures\Borders\' + ATexture + '.png');
  FHPlanes.Add(APlane);
  FPlanes.Add(APlane);
end;

function TCheckersBorder.GetBorderSize: Single;
begin
  Result := FSize;
end;

function TCheckersBorder.GetFullHeight: Single;
begin
  Result := FBoardHeight + FSize * 2;
end;

function TCheckersBorder.GetFullWidth: Single;
begin
  Result := FBoardWidth + FSize * 2;
end;

function TCheckersBorder.GetPlanes: TPlanesList;
begin
  Result := FPlanes;
end;

procedure TCheckersBorder.SetBoardSize(const AWidth, AHeight: Single);
begin
  FBoardWidth := AWidth;
  FBoardHeight := AHeight;

  FLeft.Height := AHeight;
  FRight.Height := FLeft.Height;
  FTop.Width := AWidth;
  FBottom.Width := FTop.Width;
  FLeft.Position.X := (-AWidth - FSize) / 2;
  FRight.Position.X := (AWidth + FSize) / 2;
  FTop.Position.Z := (-AHeight - FSize) / 2;
  FBottom.Position.Z := (AHeight + FSize) / 2;

  FLeftTop.Position.X := FLeft.Position.X; 
  FLeftTop.Position.Z := FTop.Position.Z;
  FLeftBottom.Position.X := FLeft.Position.X; 
  FLeftBottom.Position.Z := FBottom.Position.Z;
  FRightTop.Position.X := FRight.Position.X; 
  FRightTop.Position.Z := FTop.Position.Z;
  FRightBottom.Position.X := FRight.Position.X; 
  FRightBottom.Position.Z := FBottom.Position.Z;

  FLeftDown.Width := AHeight + FSize * 2;
  FLeftDown.Position.X := -AWidth / 2 - FSize;
  FRightDown.Width := AHeight + FSize * 2;
  FRightDown.Position.X := AWidth / 2 + FSize;
  FTopDown.Width := AWidth + FSize * 2;
  FTopDown.Position.Z := -AHeight / 2 - FSize;
  FBottomDown.Width := AWidth + FSize * 2;
  FBottomDown.Position.Z := AHeight / 2 + FSize;
end;

procedure TCheckersBorder.SetHeight(const Value: Single);
var
  vY: Single;
  i: Integer;
begin
  vY := (Value - 1) / 2;
  for i := 0 to FHPlanes.Count - 1 do
    FHPlanes[i].Position.Y := vY;
end;

procedure TCheckersBorder.SetBorderSize(const Value: Single);
begin
  FSize := Value;
  FLeft.Width := FSize;
  FRight.Width := FSize;
  FTop.Height := FSize;
  FBottom.Height := FSize;
  FLeftTop.Width := FSize;
  FLeftBottom.Width := FSize;  
  FRightTop.Width := FSize;
  FRightBottom.Width := FSize;
  FLeftTop.Height := FSize;
  FLeftBottom.Height := FSize;  
  FRightTop.Height := FSize;
  FRightBottom.Height := FSize;
end;

procedure TCheckersBorder.DoRender(var ARci: TRenderContextInfo; ARenderSelf,
  ARenderChildren: Boolean);
begin
end;

destructor TCheckersBorder.Destroy;
begin
  FHPlanes.Free;
  FPlanes.Free;
  inherited;
end;

end.
